`include "mux.v"
`include "register.v"

// TODO: add delay times - register access time and register write time (write should be longer?), specifically

/*module testRegisterBank();
  reg [4:0] Rw, Ra, Rb;
  reg  RegWr, CLK;
  reg [31:0] busW;
  wire [31:0] busA, busB;

  registers32_32 registerBank(Rw,Ra,Rb,RegWr,CLK,busW,busA,busB);

  initial begin
	$monitor ($time," Control Signals:\tRegWr=%b\tCLK=%b\tRw=%d\tRa=%d\tRb=%d\n\t\t\tOutputs:\tbusA=%b\tbusB=%b\n\t\t\tInputs:\tbusW=%b",
				RegWr,CLK,Rw,Ra,Rb, busA, busB, busW);
	//$monitor ($time," Outputs:\tbusA=%d\tbusB=%d",busA,busB);
	//$monitor ($time," Inputs:\tbusW=%d", busW);
	
	// put it through its paces
	
	// write to all of the registers - only writes on the falling edge of CLK
	
	// write to one register
	#5 CLK = 1; RegWr = 1; Rw = 5'd0; busW = 32'd0;	
	#5 CLK = 0; Ra = 5'd7;
	
	// write to one register
	#5 CLK = 1; Rw = 5'd1; busW = 32'd1;	
	#5 CLK = 0; Ra = 5'd7;  // Writes on the negative edge
	
	// write to one register
	#5 CLK = 1; Rw = 5'd2; busW = 32'd2;	
	#5 CLK = 0; Ra = 5'd7;
	
	// write to one register
	#5 CLK = 1; Rw = 5'd30; busW = -32'd519;	
	#5 CLK = 1; Ra = 5'd30;
	#5 CLK = 0;
	
	
	// read all the registers - asynchronous so dont worry about clock
	#1 Ra = 5'd0; Rb = 5'd1;
	#1 Ra = 5'd2; Rb = 5'd3;
	#1 Ra = 5'd4; Rb = 5'd5;
	#1 Ra = 5'd6; Rb = 5'd7;
	#1 Ra = 5'd8; Rb = 5'd9;
	
	#10 $finish;
  end

endmodule*/

module registers32_32(Rw,Ra,Rb,RegWr,CLK,busW,busA,busB);
	//register(q, qbar, preset, clear, write, clock,d);

	input RegWr, CLK;
	input [31:0] busW;
	output [31:0] busA, busB;

	//==================================
	// input wires to the registers 
	// (reg type so we can make them behavioral)
	// 32 inputs of 32 bits
	reg [31:0] regInputs0; 
	reg [31:0] regInputs1;
	reg [31:0] regInputs2; 
	reg [31:0] regInputs3;
	reg [31:0] regInputs4; 
	reg [31:0] regInputs5;
	reg [31:0] regInputs6; 
	reg [31:0] regInputs7;
	reg [31:0] regInputs8; 
	reg [31:0] regInputs9;
	reg [31:0] regInputs10; 
	reg [31:0] regInputs11;
	reg [31:0] regInputs12; 
	reg [31:0] regInputs13;
	reg [31:0] regInputs14; 
	reg [31:0] regInputs15;
	reg [31:0] regInputs16; 
	reg [31:0] regInputs17;
	reg [31:0] regInputs18; 
	reg [31:0] regInputs19;
	reg [31:0] regInputs20; 
	reg [31:0] regInputs21;
	reg [31:0] regInputs22; 
	reg [31:0] regInputs23;
	reg [31:0] regInputs24; 
	reg [31:0] regInputs25;
	reg [31:0] regInputs26; 
	reg [31:0] regInputs27;
	reg [31:0] regInputs28; 
	reg [31:0] regInputs29;
	reg [31:0] regInputs30; 
	reg [31:0] regInputs31;

	//==================================

	//==================================
	// output wires from the 
	// bank of registers
	// 32 32-bit wires
	wire [31:0] regOutputs0; 
	wire[31:0] regOutputs1;
	wire[31:0] regOutputs2; 
	wire[31:0] regOutputs3;
	wire[31:0] regOutputs4; 
	wire[31:0] regOutputs5;
	wire[31:0] regOutputs6; 
	wire[31:0] regOutputs7;
	wire[31:0] regOutputs8; 
	wire[31:0] regOutputs9;
	wire[31:0] regOutputs10; 
	wire[31:0] regOutputs11;
	wire[31:0] regOutputs12; 
	wire[31:0] regOutputs13;
	wire[31:0] regOutputs14; 
	wire[31:0] regOutputs15;
	wire[31:0] regOutputs16; 
	wire[31:0] regOutputs17;
	wire[31:0] regOutputs18; 
	wire[31:0] regOutputs19;
	wire[31:0] regOutputs20; 
	wire[31:0] regOutputs21;
	wire[31:0] regOutputs22; 
	wire[31:0] regOutputs23;
	wire[31:0] regOutputs24; 
	wire[31:0] regOutputs25;
	wire[31:0] regOutputs26; 
	wire[31:0] regOutputs27;
	wire[31:0] regOutputs28; 
	wire[31:0] regOutputs29;
	wire[31:0] regOutputs30; 
	wire[31:0] regOutputs31;
	//==================================


	input [4:0] Rw, Ra, Rb;
	wire [31:0] writeReg;

	// Select the data for bus A	
	MUX32_32to1 selectA (
							 regOutputs0,
							 regOutputs1,
							 regOutputs2,
							 regOutputs3,
							 regOutputs4,
							 regOutputs5,
							 regOutputs6,
							 regOutputs7,
							 regOutputs8,
							 regOutputs9,					 
							 regOutputs10,
							 regOutputs11,
							 regOutputs12,
							 regOutputs13,
							 regOutputs14,
							 regOutputs15,
							 regOutputs16,
							 regOutputs17,
							 regOutputs18,
							 regOutputs19,					 
							 regOutputs20,					 
							 regOutputs21,					 
							 regOutputs22,				 
							 regOutputs23,					 
							 regOutputs24,					 
							 regOutputs25,					 
							 regOutputs26,					 
							 regOutputs27,
							 regOutputs28,					 
							 regOutputs29,					 
							 regOutputs30,					 					 
							 regOutputs31,
							 Ra,           // Control signal
							 busA          // Destination of selected register output
						 );        

	// Select the data for busB
	MUX32_32to1 selectB (
							 regOutputs0,
							 regOutputs1,
							 regOutputs2,
							 regOutputs3,
							 regOutputs4,
							 regOutputs5,
							 regOutputs6,
							 regOutputs7,
							 regOutputs8,
							 regOutputs9,					 
							 regOutputs10,
							 regOutputs11,
							 regOutputs12,
							 regOutputs13,
							 regOutputs14,
							 regOutputs15,
							 regOutputs16,
							 regOutputs17,
							 regOutputs18,
							 regOutputs19,					 
							 regOutputs20,					 
							 regOutputs21,					 
							 regOutputs22,				 
							 regOutputs23,					 
							 regOutputs24,					 
							 regOutputs25,					 
							 regOutputs26,					 
							 regOutputs27,
							 regOutputs28,					 
							 regOutputs29,					 
							 regOutputs30,					 					 
							 regOutputs31,
							 Rb,
							 busB
						 );

	// declare registers
	register a0 (regOutputs0,,,,RegWr, CLK, regInputs0),
			 a1 (regOutputs1,,,,RegWr, CLK, regInputs1),
			 a2 (regOutputs2,,,,RegWr, CLK, regInputs2),
			 a3 (regOutputs3,,,,RegWr, CLK, regInputs3),
			 a4 (regOutputs4,,,,RegWr, CLK, regInputs4),
			 a5 (regOutputs5,,,,RegWr, CLK, regInputs5),
			 a6 (regOutputs6,,,,RegWr, CLK, regInputs6),
			 a7 (regOutputs7,,,,RegWr, CLK, regInputs7),
			 a8 (regOutputs8,,,,RegWr, CLK, regInputs8),
			 a9 (regOutputs9,,,,RegWr, CLK, regInputs9),
			 a10 (regOutputs10,,,,RegWr, CLK, regInputs10),
			 a11 (regOutputs11,,,,RegWr, CLK, regInputs11),
			 a12 (regOutputs12,,,,RegWr, CLK, regInputs12),
			 a13 (regOutputs13,,,,RegWr, CLK, regInputs13),
			 a14 (regOutputs14,,,,RegWr, CLK, regInputs14),
			 a15 (regOutputs15,,,,RegWr, CLK, regInputs15),
			 a16 (regOutputs16,,,,RegWr, CLK, regInputs16),
			 a17 (regOutputs17,,,,RegWr, CLK, regInputs17),
			 a18 (regOutputs18,,,,RegWr, CLK, regInputs18),
			 a19 (regOutputs19,,,,RegWr, CLK, regInputs19),
			 a20 (regOutputs20,,,,RegWr, CLK, regInputs20),
			 a21 (regOutputs21,,,,RegWr, CLK, regInputs21),
			 a22 (regOutputs22,,,,RegWr, CLK, regInputs22),
			 a23 (regOutputs23,,,,RegWr, CLK, regInputs23),
			 a24 (regOutputs24,,,,RegWr, CLK, regInputs24),
			 a25 (regOutputs25,,,,RegWr, CLK, regInputs25),
			 a26 (regOutputs26,,,,RegWr, CLK, regInputs26),
			 a27 (regOutputs27,,,,RegWr, CLK, regInputs27),
			 a28 (regOutputs28,,,,RegWr, CLK, regInputs28),
			 a29 (regOutputs29,,,,RegWr, CLK, regInputs29),
			 a30 (regOutputs30,,,,RegWr, CLK, regInputs30),		 
			 a31 (regOutputs31,,,,RegWr, CLK, regInputs31);

	// this always block handles when busW writes to the specified register
	always@(negedge CLK)
	begin	
	  // Add a 2-unit time delay for writing
	  #2 if( (Rw >= 0) && (Rw <= 31) && (RegWr == 1)) // if the RegWr is set, write busW to Rw
	   case(Rw)
		5'd0: regInputs0 = busW;
		5'd1: regInputs1 = busW;
		5'd2: regInputs2 = busW;
		5'd3: regInputs3 = busW;
		5'd4: regInputs4 = busW;
		5'd5: regInputs5 = busW;
		5'd6: regInputs6 = busW;
		5'd7: regInputs7 = busW;
		5'd8: regInputs8 = busW;
		5'd9: regInputs9 = busW;
		5'd10: regInputs10 = busW;
		5'd11: regInputs11 = busW;
		5'd12: regInputs12 = busW;
		5'd13: regInputs13 = busW;
		5'd14: regInputs14 = busW;
		5'd15: regInputs15 = busW;
		5'd16: regInputs16 = busW;
		5'd17: regInputs17 = busW;
		5'd18: regInputs18 = busW;
		5'd19: regInputs19 = busW;
		5'd20: regInputs20 = busW;
		5'd21: regInputs21 = busW;
		5'd22: regInputs22 = busW;
		5'd23: regInputs23 = busW;
		5'd24: regInputs24 = busW;
		5'd25: regInputs25 = busW;
		5'd26: regInputs26 = busW;
		5'd27: regInputs27 = busW;
		5'd28: regInputs28 = busW;
		5'd29: regInputs29 = busW;
		5'd30: regInputs30 = busW;
		5'd31: regInputs31 = busW;
	   endcase
	end

endmodule


